package top.xia17.plugins.fast.dynamic.datasource.mgmt;

import top.xia17.plugins.fast.common.crypto.asymmetric.RsaUtil;
import top.xia17.plugins.fast.common.database.dynamic.DsManager;
import top.xia17.plugins.fast.common.database.jpa.extension.JpaServiceImpl;
import top.xia17.plugins.fast.common.exceptions.BadRequestException;
import lombok.RequiredArgsConstructor;
import top.xia17.plugins.fast.dynamic.datasource.dao.DatasourceEntity;
import top.xia17.plugins.fast.dynamic.datasource.dao.DatasourceRepository;

import jakarta.persistence.EntityNotFoundException;
import java.util.Optional;

/**
 * 数据源service
 *
 * @author xia17
 * @date 2022/4/13
 */
@RequiredArgsConstructor
public class DatasourceService extends JpaServiceImpl<DatasourceEntity, Long, DatasourceRepository> {

    /**
     * 主要数据源的名字 master
     */
    private final static String DS_MASTER_NAME = "master";

    private final RsaUtil rsaUtil;
    private final DsManager dsManager;

    /**
     * 验证名称是否合法
     *
     * @param engName /
     */
    private void provingEngName(String engName) {
        // 不能叫master
        if (DS_MASTER_NAME.equals(engName)) {
            throw new BadRequestException("数据源英文名不能为" + engName);
        }

    }

    @Override
    public void createBefore(DatasourceEntity entity) {
        this.provingEngName(entity.getEngName());
        if (baseRepository.countAllByEngName(entity.getEngName()) > 0) {
            throw new BadRequestException("数据源英文名已存在！");
        }
        // 密码加密
        entity.setPassword(rsaUtil.encryptStr(entity.getPassword()));
    }

    @Override
    public void updateBefore(DatasourceEntity entity, DatasourceEntity resource) {
        this.provingEngName(entity.getEngName());
        if (!entity.getEngName().equals(resource.getEngName()) && baseRepository.countAllByEngName(entity.getEngName()) > 0) {
            throw new BadRequestException("数据源英文名已存在！");
        }
    }

    @Override
    public void updateProperty(DatasourceEntity entity, DatasourceEntity resource) {
        entity.setEngName(resource.getEngName())
                .setCnName(resource.getCnName())
                .setType(resource.getType())
                .setUrl(resource.getUrl())
                .setUsername(resource.getUsername())
                // 密码加密
                .setPassword(rsaUtil.encryptStr(resource.getPassword()))
                .setDriver(resource.getDriver())
                // .setEnabled(dataSourceEntity.getEnabled()) 在这里不可修改是否启用
                .setSchemaName(resource.getSchemaName());
    }

    @Override
    public void updateAfter(DatasourceEntity entity) {
        // 更新数据源
        if (dsManager.exist(entity.getEngName())) {
            // 密码解密
            String password = rsaUtil.decryptStr(entity.getPassword());
            dsManager.add(entity.buildDatasourceInfo(password));
        }
    }

    @Override
    public void deleteAfter(DatasourceEntity entity) {
        dsManager.remove(entity.getEngName());
    }

    /**
     * 切换enabled状态
     * 如果切换成禁用，将会从内存中移除数据源
     *
     * @param id /
     */
    public synchronized void switchEnabled(Long id) {
        DatasourceEntity datasourceEntity = this.findById(id).orElseThrow(EntityNotFoundException::new);
        datasourceEntity.setEnabled(!datasourceEntity.getEnabled());
        if (!datasourceEntity.getEnabled()) {
            dsManager.remove(datasourceEntity.getEngName());
        }
    }

    /**
     * 通过engName查询
     *
     * @param engName /
     * @return /
     */
    public Optional<DatasourceEntity> findByEngName(String engName) {
        return baseRepository.findByEngName(engName);
    }

}
